Skip to content

[pull] master from ruby:master#1076

Merged
pull[bot] merged 1 commit into
turkdevops:masterfrom
ruby:master
Jun 3, 2026
Merged

[pull] master from ruby:master#1076
pull[bot] merged 1 commit into
turkdevops:masterfrom
ruby:master

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Jun 3, 2026

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

* ZJIT: Implement Polymorphic Definedivar

Closes: Shopify#980

Build polymorphic shape/type branches for definedivar in HIR. For each profiled T_OBJECT shape, specialize defined?(`@ivar`) to a constant pushval or nil based on the compile-time ivar index check.

DefinedIvar already profiles self on monomorphic shape guard failures for recompilation, so the recompiled HIR can use the collected polymorphic shapes while keeping a generic DefinedIvar fallback for misses and unsupported shapes.


## Benchmark
### lobsters
Summary:
```diff
- dynamic_definedivar_count:   1,294,854 ( 0.7%)
+ dynamic_definedivar_count:     503,058 ( 0.3%)

  ratio_in_zjit:                                     88.4%
```

```
zjit-master: ruby 4.1.0dev (2026-05-23T00:08:49Z master 5855d61) +ZJIT stats +PRISM [arm64-darwin25]
zjit-polymorphic-definedivar: ruby 4.1.0dev (2026-05-23T07:11:22Z zjit-polymorphic-d.. f75a82e7f1) +ZJIT stats +PRISM [arm64-darwin25]
last_commit=ZJIT: Implement Polymorphic Definedivar

--------  ----------------  ---------------------------------  ------------------------------------  ----------------------------------------
bench     zjit-master (ms)  zjit-polymorphic-definedivar (ms)  zjit-polymorphic-definedivar 1st itr  zjit-master/zjit-polymorphic-definedivar
lobsters      529.9 ± 3.6%                       504.2 ± 7.7%                                 1.148                                     1.051
--------  ----------------  ---------------------------------  ------------------------------------  ----------------------------------------
```

Full stats details below:
<details>

<summary>before patch</summary>

```
Top-2 not optimized method types for send (100.0% of total 65,120):
       null: 44,877 (68.9%)
  optimized: 20,243 (31.1%)
Top-3 not optimized method types for send_without_block (100.0% of total 716,678):
        optimized_send: 711,905 (99.3%)
  optimized_block_call:   4,299 ( 0.6%)
                zsuper:     474 ( 0.1%)
Top-1 not optimized method types for super (100.0% of total 3,678):
  attrset: 3,678 (100.0%)
Top-1 instructions with uncategorized fallback reason (100.0% of total 65,868):
  opt_send_without_block: 65,868 (100.0%)
Top-20 send fallback reasons (99.5% of total 22,386,632):
                             invokeblock_not_specialized: 5,946,612 (26.6%)
                            one_or_more_complex_arg_pass: 4,376,419 (19.5%)
                          send_without_block_polymorphic: 3,748,855 (16.7%)
                          send_without_block_no_profiles: 2,830,116 (12.6%)
                          send_without_block_megamorphic: 1,108,467 ( 5.0%)
                             sendforward_not_specialized:   971,957 ( 4.3%)
                                        send_polymorphic:   806,862 ( 3.6%)
  send_without_block_not_optimized_method_type_optimized:   716,204 ( 3.2%)
                                       super_polymorphic:   337,181 ( 1.5%)
                                   too_many_args_for_lir:   333,633 ( 1.5%)
                      send_not_optimized_need_permission:   238,842 ( 1.1%)
        send_without_block_not_optimized_need_permission:   180,946 ( 0.8%)
                                        send_no_profiles:   177,008 ( 0.8%)
                                     argc_param_mismatch:   124,061 ( 0.6%)
                                 super_complex_args_pass:    89,280 ( 0.4%)
                      invokesuperforward_not_specialized:    80,729 ( 0.4%)
                                           uncategorized:    65,868 ( 0.3%)
                          send_not_optimized_method_type:    65,120 ( 0.3%)
                                        super_from_block:    43,185 ( 0.2%)
                                obj_to_string_not_string:    42,731 ( 0.2%)
Top-4 setivar fallback reasons (100.0% of total 4,182,333):
            not_monomorphic: 3,969,254 (94.9%)
               not_t_object:   119,505 ( 2.9%)
                    complex:    93,131 ( 2.2%)
  new_shape_needs_extension:       443 ( 0.0%)
Top-2 getivar fallback reasons (100.0% of total 11,716,846):
  not_monomorphic: 11,537,525 (98.5%)
          complex:    179,321 ( 1.5%)
Top-3 definedivar fallback reasons (100.0% of total 1,294,854):
  not_monomorphic: 1,289,423 (99.6%)
          complex:     5,122 ( 0.4%)
     not_t_object:       309 ( 0.0%)
Top-5 invokeblock handler (100.0% of total 6,968,323):
  monomorphic_ifunc: 4,143,418 (59.5%)
  monomorphic_other: 1,444,525 (20.7%)
   monomorphic_iseq:   865,749 (12.4%)
        polymorphic:   508,677 ( 7.3%)
        megamorphic:     5,954 ( 0.1%)
Top-6 getblockparamproxy handler (100.0% of total 3,321,873):
  polymorphic: 2,370,458 (71.4%)
          nil:   492,185 (14.8%)
         iseq:   242,627 ( 7.3%)
  no_profiles:   168,826 ( 5.1%)
         proc:    40,245 ( 1.2%)
  megamorphic:     7,532 ( 0.2%)
Top-7 popular complex argument-parameter features not optimized (100.0% of total 4,677,994):
    caller_blockarg: 3,092,361 (66.1%)
  param_forwardable:   697,044 (14.9%)
         param_rest:   409,311 ( 8.7%)
       caller_kwarg:   193,462 ( 4.1%)
       param_kwrest:   143,181 ( 3.1%)
    caller_kw_splat:    85,992 ( 1.8%)
       caller_splat:    56,643 ( 1.2%)
Top-3 compile error reasons (100.0% of total 196,397):
                  exception_handler: 192,000 (97.8%)
             native_stack_too_large:   4,342 ( 2.2%)
  validation_mismatched_block_arity:      55 ( 0.0%)
Top-2 unhandled HIR insns (100.0% of total 229,881):
          throw: 194,104 (84.4%)
  invokebuiltin:  35,777 (15.6%)
Top-19 side exit reasons (100.0% of total 8,637,525):
                   guard_type_failure: 7,692,359 (89.1%)
                   unhandled_hir_insn:   229,881 ( 2.7%)
                        compile_error:   196,397 ( 2.3%)
          patchpoint_method_redefined:   118,680 ( 1.4%)
      block_param_proxy_fallback_miss:   112,551 ( 1.3%)
                      no_profile_send:    93,334 ( 1.1%)
            block_param_proxy_not_nil:    75,195 ( 0.9%)
     patchpoint_stable_constant_names:    55,819 ( 0.6%)
        patchpoint_no_singleton_class:    19,352 ( 0.2%)
                  unhandled_block_arg:    14,541 ( 0.2%)
  block_param_proxy_not_iseq_or_ifunc:    13,401 ( 0.2%)
               fixnum_lshift_overflow:    10,165 ( 0.1%)
                   guard_less_failure:     3,120 ( 0.0%)
                  guard_shape_failure:     1,302 ( 0.0%)
             guard_greater_eq_failure:       941 ( 0.0%)
             guard_super_method_entry:       407 ( 0.0%)
                            interrupt:        49 ( 0.0%)
               obj_to_string_fallback:        30 ( 0.0%)
             guard_not_shared_failure:         1 ( 0.0%)
                             send_count: 182,469,185
                     dynamic_send_count:  22,386,632 (12.3%)
                   optimized_send_count: 160,082,553 (87.7%)
                  dynamic_setivar_count:   4,182,333 ( 2.3%)
                  dynamic_getivar_count:  11,716,846 ( 6.4%)
              dynamic_definedivar_count:   1,294,854 ( 0.7%)
              iseq_optimized_send_count:  54,154,353 (29.7%)
      inline_cfunc_optimized_send_count:  74,812,159 (41.0%)
       inline_iseq_optimized_send_count:   6,346,705 ( 3.5%)
non_variadic_cfunc_optimized_send_count:  13,789,249 ( 7.6%)
    variadic_cfunc_optimized_send_count:  10,980,087 ( 6.0%)
compiled_iseq_count:                                  6,166
compiled_side_exit_count:                            80,485
failed_iseq_count:                                        3
compile_time:                                       2,462ms
compile_side_exit_time:                               113ms
compile_side_exit_time_ratio:                          4.6%
compile_hir_time:                                     798ms
compile_hir_build_time:                               238ms
compile_hir_strength_reduce_time:                     322ms
compile_hir_canonicalize_time:                         49ms
compile_hir_fold_constants_time:                       37ms
compile_hir_clean_cfg_time:                            26ms
compile_hir_eliminate_dead_code_time:                  30ms
compile_lir_time:                                   1,525ms
profile_time:                                          39ms
gc_time:                                               33ms
invalidation_time:                                     14ms
vm_write_jit_frame_count:                       137,433,269
vm_write_sp_count:                              137,433,269
vm_write_locals_count:                          131,272,119
vm_write_stack_count:                           131,272,119
vm_write_to_parent_iseq_local_count:                688,492
guard_type_count:                               145,711,992
guard_type_exit_ratio:                                 5.3%
guard_shape_count:                               36,890,099
guard_shape_exit_ratio:                                0.0%
load_field_count:                               210,155,590
store_field_count:                               15,758,742
side_exit_size:                                  13,563,708
code_region_bytes:                               33,505,280
side_exit_size_ratio:                                 40.5%
zjit_alloc_bytes:                                22,783,024
total_mem_bytes:                                 56,288,304
side_exit_count:                                  8,637,525
total_insn_count:                               995,180,861
vm_insn_count:                                  115,515,525
zjit_insn_count:                                879,665,336
ratio_in_zjit:                                        88.4%
```

</details>

<details>

<summary>after patch</summary>

```
Top-2 not optimized method types for send (100.0% of total 65,119):
       null: 44,877 (68.9%)
  optimized: 20,242 (31.1%)
Top-3 not optimized method types for send_without_block (100.0% of total 716,636):
        optimized_send: 711,869 (99.3%)
  optimized_block_call:   4,293 ( 0.6%)
                zsuper:     474 ( 0.1%)
Top-1 not optimized method types for super (100.0% of total 3,676):
  attrset: 3,676 (100.0%)
Top-1 instructions with uncategorized fallback reason (100.0% of total 65,866):
  opt_send_without_block: 65,866 (100.0%)
Top-20 send fallback reasons (99.5% of total 22,409,237):
                             invokeblock_not_specialized: 5,946,405 (26.5%)
                            one_or_more_complex_arg_pass: 4,376,457 (19.5%)
                          send_without_block_polymorphic: 3,775,975 (16.9%)
                          send_without_block_no_profiles: 2,830,029 (12.6%)
                          send_without_block_megamorphic: 1,104,527 ( 4.9%)
                             sendforward_not_specialized:   971,924 ( 4.3%)
                                        send_polymorphic:   806,852 ( 3.6%)
  send_without_block_not_optimized_method_type_optimized:   716,162 ( 3.2%)
                                       super_polymorphic:   337,178 ( 1.5%)
                                   too_many_args_for_lir:   333,625 ( 1.5%)
                      send_not_optimized_need_permission:   238,842 ( 1.1%)
        send_without_block_not_optimized_need_permission:   180,949 ( 0.8%)
                                        send_no_profiles:   176,799 ( 0.8%)
                                     argc_param_mismatch:   124,064 ( 0.6%)
                                 super_complex_args_pass:    89,280 ( 0.4%)
                      invokesuperforward_not_specialized:    80,723 ( 0.4%)
                                           uncategorized:    65,866 ( 0.3%)
                          send_not_optimized_method_type:    65,119 ( 0.3%)
                                        super_from_block:    43,182 ( 0.2%)
                                obj_to_string_not_string:    42,725 ( 0.2%)
Top-4 setivar fallback reasons (100.0% of total 4,182,216):
            not_monomorphic: 3,969,159 (94.9%)
               not_t_object:   119,484 ( 2.9%)
                    complex:    93,131 ( 2.2%)
  new_shape_needs_extension:       442 ( 0.0%)
Top-2 getivar fallback reasons (100.0% of total 11,716,471):
  not_monomorphic: 11,537,150 (98.5%)
          complex:    179,321 ( 1.5%)
Top-3 definedivar fallback reasons (100.0% of total 503,058):
  not_monomorphic: 498,173 (99.0%)
          complex:   4,576 ( 0.9%)
     not_t_object:     309 ( 0.1%)
Top-5 invokeblock handler (100.0% of total 6,968,099):
  monomorphic_ifunc: 4,143,324 (59.5%)
  monomorphic_other: 1,444,457 (20.7%)
   monomorphic_iseq:   865,705 (12.4%)
        polymorphic:   508,659 ( 7.3%)
        megamorphic:     5,954 ( 0.1%)
Top-6 getblockparamproxy handler (100.0% of total 3,321,803):
  polymorphic: 2,370,425 (71.4%)
          nil:   492,172 (14.8%)
         iseq:   242,810 ( 7.3%)
  no_profiles:   168,625 ( 5.1%)
         proc:    40,239 ( 1.2%)
  megamorphic:     7,532 ( 0.2%)
Top-7 popular complex argument-parameter features not optimized (100.0% of total 4,678,011):
    caller_blockarg: 3,092,480 (66.1%)
  param_forwardable:   697,011 (14.9%)
         param_rest:   409,285 ( 8.7%)
       caller_kwarg:   193,450 ( 4.1%)
       param_kwrest:   143,179 ( 3.1%)
    caller_kw_splat:    85,971 ( 1.8%)
       caller_splat:    56,635 ( 1.2%)
Top-3 compile error reasons (100.0% of total 196,386):
                  exception_handler: 191,989 (97.8%)
             native_stack_too_large:   4,342 ( 2.2%)
  validation_mismatched_block_arity:      55 ( 0.0%)
Top-2 unhandled HIR insns (100.0% of total 229,876):
          throw: 194,101 (84.4%)
  invokebuiltin:  35,775 (15.6%)
Top-19 side exit reasons (100.0% of total 8,638,646):
                   guard_type_failure: 7,693,566 (89.1%)
                   unhandled_hir_insn:   229,876 ( 2.7%)
                        compile_error:   196,386 ( 2.3%)
          patchpoint_method_redefined:   118,676 ( 1.4%)
      block_param_proxy_fallback_miss:   112,548 ( 1.3%)
                      no_profile_send:    93,330 ( 1.1%)
            block_param_proxy_not_nil:    75,195 ( 0.9%)
     patchpoint_stable_constant_names:    55,792 ( 0.6%)
        patchpoint_no_singleton_class:    19,326 ( 0.2%)
                  unhandled_block_arg:    14,540 ( 0.2%)
  block_param_proxy_not_iseq_or_ifunc:    13,401 ( 0.2%)
               fixnum_lshift_overflow:    10,165 ( 0.1%)
                   guard_less_failure:     3,119 ( 0.0%)
                  guard_shape_failure:     1,302 ( 0.0%)
             guard_greater_eq_failure:       941 ( 0.0%)
             guard_super_method_entry:       407 ( 0.0%)
                            interrupt:        45 ( 0.0%)
               obj_to_string_fallback:        30 ( 0.0%)
             guard_not_shared_failure:         1 ( 0.0%)
                             send_count: 182,477,537
                     dynamic_send_count:  22,409,237 (12.3%)
                   optimized_send_count: 160,068,300 (87.7%)
                  dynamic_setivar_count:   4,182,216 ( 2.3%)
                  dynamic_getivar_count:  11,716,471 ( 6.4%)
              dynamic_definedivar_count:     503,058 ( 0.3%)
              iseq_optimized_send_count:  54,138,292 (29.7%)
      inline_cfunc_optimized_send_count:  74,815,196 (41.0%)
       inline_iseq_optimized_send_count:   6,346,484 ( 3.5%)
non_variadic_cfunc_optimized_send_count:  13,788,597 ( 7.6%)
    variadic_cfunc_optimized_send_count:  10,979,731 ( 6.0%)
compiled_iseq_count:                                  6,167
compiled_side_exit_count:                            80,471
failed_iseq_count:                                        3
compile_time:                                       2,711ms
compile_side_exit_time:                               125ms
compile_side_exit_time_ratio:                          4.6%
compile_hir_time:                                     870ms
compile_hir_build_time:                               266ms
compile_hir_strength_reduce_time:                     347ms
compile_hir_canonicalize_time:                         52ms
compile_hir_fold_constants_time:                       40ms
compile_hir_clean_cfg_time:                            27ms
compile_hir_eliminate_dead_code_time:                  32ms
compile_lir_time:                                   1,680ms
profile_time:                                          48ms
gc_time:                                               32ms
invalidation_time:                                     15ms
vm_write_jit_frame_count:                       137,425,789
vm_write_sp_count:                              137,425,789
vm_write_locals_count:                          131,264,963
vm_write_stack_count:                           131,264,963
vm_write_to_parent_iseq_local_count:                688,457
guard_type_count:                               146,412,455
guard_type_exit_ratio:                                 5.3%
guard_shape_count:                               36,937,934
guard_shape_exit_ratio:                                0.0%
load_field_count:                               211,394,883
store_field_count:                               15,778,119
side_exit_size:                                  13,563,624
code_region_bytes:                               33,505,280
side_exit_size_ratio:                                 40.5%
zjit_alloc_bytes:                                22,870,223
total_mem_bytes:                                 56,375,503
side_exit_count:                                  8,638,646
total_insn_count:                               995,144,390
vm_insn_count:                                  115,472,694
zjit_insn_count:                                879,671,696
ratio_in_zjit:                                        88.4%
```

</details>

* ZJIT: Add TODO for deduplicating DefinedIvar specialization

* ZJIT: Add more DefinedIvar HIR tests

Cover unsupported receiver profiles and a mixed polymorphic profile with a generic DefinedIvar fallback.

* ZJIT: Add more DefinedIvar polymorphic HIR test

Cover polymorphic definedivar profiles with:
- complex path
- non-T_OBJECT path
@pull pull Bot locked and limited conversation to collaborators Jun 3, 2026
@pull pull Bot added the ⤵️ pull label Jun 3, 2026
@pull pull Bot merged commit f717edc into turkdevops:master Jun 3, 2026
0 of 2 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant